home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 051-060 / amok58 / kme / kme.mod < prev    next >
Text File  |  1993-11-04  |  54KB  |  1,923 lines

  1. (*---------------------------------------------------------------------------
  2.   :Program.     KME.mod
  3.   :Contents.    KeyMap-Editor
  4.   :Author.      Christian Stiens
  5.   :Address.     Heustiege 2, W-4710 Lüdinghausen
  6.   :Copyright.   Freeware
  7.   :Language.    Oberon
  8.   :Translator.  A+L Amiga Oberon V2.01
  9.   :History.     V1.0, 15-Jul-91
  10.   :Imports.     Iconify (Steffen Köhler)
  11. ---------------------------------------------------------------------------*)
  12.  
  13. MODULE KME;
  14.  
  15.   IMPORT
  16.  
  17.     (* $IF debug *)
  18.  
  19.     io,NoGuru,ARP,
  20.  
  21.     (* $END *)
  22.  
  23.     I  : Intuition,
  24.     d  : Dos,
  25.     fs : FileSystem,
  26.     fr : FileReq,
  27.     g  : Graphics,
  28.     e  : Exec,
  29.     km : KeyMap,
  30.     ic : Iconify,
  31.     ol : OberonLib,
  32.     rq : Requests,
  33.     st : Strings,
  34.     s  : SYSTEM;
  35.  
  36.   CONST
  37.     kmr  = "KME Request:";
  38.     ok   = " Ok ";
  39.     rtry = "Retry";
  40.     cncl = "Cancel";
  41.     nos  = "";
  42.     oom  = "Out of memory";
  43.     ooc  = "Out of chip mem";
  44.     cow  = "Can't open window";
  45.     clk  = "Can't load keymap";
  46.     csk  = "Can't save keymap";
  47.     wer  = "Write error, delete corrupt file?";
  48.     fae  = "File already exists";
  49.     ovw  = "Overwrite";
  50.     load = "Map is modified, really load another?";
  51.     quit = "Keymap has been modified, really quit?";
  52.     kme  = "KME Keymap Editor V1.0";
  53.     cprt = "© 1991 by Christian Stiens";
  54.     please = "Yes, please!";
  55.     forget = "Forget it!";
  56.  
  57.     strLen = 80;
  58.     numGads = 130;
  59.     keyHeight = 14;
  60.  
  61.     W1 = 24;
  62.     W2 = 30;
  63.     S1 = 10;
  64.     C1 = 28;
  65.     S2 = (S1+6*W1-W2*4) DIV 2;
  66.     X1 = -10;
  67.     X2 = 0;
  68.     Y1 = 11;
  69.  
  70.     (* Key.type *)
  71.     white = 0;
  72.     gray  = 1;
  73.     nop   = 2;
  74.  
  75.     (* Gadget ID's *)
  76.     idKey=5;
  77.     idAbout=10;
  78.     idIconify=20;
  79.     idQuit=30;
  80.     idMod=50;
  81.     idLoad=101;
  82.     idSave=102;
  83.     idShift=203;
  84.     idAlt=204;
  85.     idControl=205;
  86.     idDownup=206;
  87.     idDead=207;
  88.     idString=208;
  89.     idNop=209;
  90.     idCapsable=210;
  91.     idRepeatable=211;
  92.     idUndo=112;
  93.     idStr=300;
  94.  
  95.  
  96.   TYPE
  97.  
  98.     KeyMapPtr  = POINTER TO KeyMap;
  99.  
  100.     KeyMap  = STRUCT
  101.       loKeyMapTypes : POINTER TO ARRAY 64 OF SHORTSET;
  102.       loKeyMap      : POINTER TO ARRAY 64 OF LONGINT;
  103.       loCapsable    : POINTER TO ARRAY  8 OF SHORTSET;
  104.       loRepeatable  : POINTER TO ARRAY  8 OF SHORTSET;
  105.       hiKeyMapTypes : POINTER TO ARRAY 56 OF SHORTSET;
  106.       hiKeyMap      : POINTER TO ARRAY 56 OF LONGINT;
  107.       hiCapsable    : POINTER TO ARRAY  7 OF SHORTSET;
  108.       hiRepeatable  : POINTER TO ARRAY  7 OF SHORTSET;
  109.     END;
  110.  
  111.     String = ARRAY strLen OF CHAR;
  112.     Str4   = ARRAY 4 OF CHAR;
  113.  
  114.     Key = STRUCT
  115.       type  : SHORTINT;
  116.       width : INTEGER;
  117.       name  : ARRAY 4 OF CHAR;
  118.       code  : SHORTINT;
  119.     END;
  120.  
  121.     StrDeskr = ARRAY 8 OF STRUCT
  122.       len,offs: SHORTINT;
  123.     END;
  124.  
  125.     StrDeskrPtr = POINTER TO StrDeskr;
  126.  
  127.     DeadDeskr = ARRAY 8 OF STRUCT
  128.       type,val: SHORTINT;
  129.     END;
  130.  
  131.     DeadDeskrPtr = POINTER TO DeadDeskr;
  132.  
  133.  
  134.   VAR
  135.     attr        : g.TextAttr;
  136.     nw          : I.NewWindow;
  137.     win         : I.WindowPtr;
  138.     rp          : g.RastPortPtr;
  139.     mes         : I.IntuiMessage;
  140.     font        : g.TextFontPtr;
  141.     msg         : I.IntuiMessagePtr;
  142.     keyMap      : KeyMapPtr;
  143.     gadCnt      : INTEGER;
  144.     strCnt      : INTEGER;
  145.     gad         : ARRAY numGads OF I.Gadget;
  146.     buffer      : ARRAY 8 OF String;
  147.     undobf      : ARRAY 8 OF String;
  148.     strInf      : ARRAY 8 OF I.StringInfo;
  149.     pat         : ARRAY 2 OF INTEGER;
  150.     clickedGad  : I.GadgetPtr;
  151.     gadget      : I.GadgetPtr;
  152.     gadID,i     : INTEGER;
  153.     lastKeyGad  : I.GadgetPtr;
  154.     kmeIcon     : I.Image;
  155.     kmeIconData : POINTER TO ARRAY 360 OF INTEGER;
  156.     iconX,iconY : INTEGER;
  157.     kmePic      : I.Image;
  158.     kmePicData  : POINTER TO ARRAY 132 OF INTEGER;
  159.     type        : SHORTSET;
  160.     rawCode     : INTEGER;
  161.     oldCode     : INTEGER;
  162.     keyModified : BOOLEAN;
  163.     mapModified : BOOLEAN;
  164.     makeGads    : BOOLEAN;
  165.     fileName    : String;
  166.     seg,newSeg  : e.BPTR;
  167.     string      : String;
  168.     zz          : POINTER TO ARRAY (22+2)*2 OF INTEGER;
  169.     dfltKeyMap  : KeyMap;
  170.     loTypes     : ARRAY 64 OF SHORTSET;
  171.     hiTypes     : ARRAY 56 OF SHORTSET;
  172.     loCaps      : ARRAY 8 OF SHORTSET;
  173.     hiCaps      : ARRAY 7 OF SHORTSET;
  174.     loRepeat    : ARRAY 8 OF SHORTSET;
  175.     hiRepeat    : ARRAY 7 OF SHORTSET;
  176.     loMap       : ARRAY 64 OF LONGINT;
  177.     hiMap       : ARRAY 56 OF LONGINT;
  178.     deadLen     : INTEGER;
  179.     reloTab     : ARRAY 130 OF LONGINT;
  180.     reloTabPtr  : INTEGER;
  181.     chipBuf     : POINTER TO ARRAY 128 OF BYTE;
  182.     dummy       : LONGINT;
  183.  
  184.  
  185.   TYPE
  186.     KeyRow0 = ARRAY 13 OF Key;
  187.     KeyRow1 = ARRAY 23 OF Key;
  188.     KeyRow2 = ARRAY 19 OF Key;
  189.     KeyRow3 = ARRAY 21 OF Key;
  190.     KeyRow4 = ARRAY 22 OF Key;
  191.     KeyRow5 = ARRAY  9 OF Key;
  192.  
  193.   CONST
  194.     keyRow0 = KeyRow0(
  195.       1,W1,"Esc",69,
  196.       nop,S1,nos,0,
  197.       1,W2,"f1",80,
  198.       1,W2,"f2",81,
  199.       1,W2,"f3",82,
  200.       1,W2,"f4",83,
  201.       1,W2,"f5",84,
  202.       nop,S1,nos,0,
  203.       1,W2,"f6",85,
  204.       1,W2,"f7",86,
  205.       1,W2,"f8",87,
  206.       1,W2,"f9",88,
  207.       1,W2,"f0",89);
  208.  
  209.     keyRow1 = KeyRow1(
  210.       1,W1+S1,"`",0,
  211.       0,W1,"1",1,
  212.       0,W1,"2",2,
  213.       0,W1,"3",3,
  214.       0,W1,"4",4,
  215.       0,W1,"5",5,
  216.       0,W1,"6",6,
  217.       0,W1,"7",7,
  218.       0,W1,"8",8,
  219.       0,W1,"9",9,
  220.       0,W1,"0",10,
  221.       0,W1,"ß",11,
  222.       0,W1,"'",12,
  223.       0,W1,"\\",13,
  224.       1,W1,"Bs",65,
  225.       nop,S1,nos,0,
  226.       1,W1*3 DIV 2,"Del",70,
  227.       1,W1*3 DIV 2,"Help",95,
  228.       nop,S1,nos,0,
  229.       1,W1,"[",90,
  230.       1,W1,"]",91,
  231.       1,W1,"/",92,
  232.       1,W1,"*",93);
  233.  
  234.     keyRow2 = KeyRow2(
  235.       1,W1+S1+W1 DIV 2,"Tab",66,
  236.       0,W1,"Q",16,
  237.       0,W1,"W",17,
  238.       0,W1,"E",18,
  239.       0,W1,"R",19,
  240.       0,W1,"T",20,
  241.       0,W1,"Z",21,
  242.       0,W1,"U",22,
  243.       0,W1,"I",23,
  244.       0,W1,"O",24,
  245.       0,W1,"P",25,
  246.       0,W1,"Ü",26,
  247.       0,W1,"+",27,
  248.       1,W1*3 DIV 2,"Rtrn",68,
  249.       nop,S1+W1*3+S1,nos,0,
  250.       0,W1,"7",61,
  251.       0,W1,"8",62,
  252.       0,W1,"9",63,
  253.       1,W1,"-",74);
  254.  
  255.     keyRow3 = KeyRow3(
  256.       1,C1,"Ctrl",99,
  257.       1,W1,"Caps",98,
  258.       0,W1,"A",32,
  259.       0,W1,"S",33,
  260.       0,W1,"D",34,
  261.       0,W1,"F",35,
  262.       0,W1,"G",36,
  263.       0,W1,"H",37,
  264.       0,W1,"J",38,
  265.       0,W1,"K",39,
  266.       0,W1,"L",40,
  267.       0,W1,"Ö",41,
  268.       0,W1,"Ä",42,
  269.       0,W1,"#",43,
  270.       nop,S1+W1*2-C1+S1+W1,nos,0,
  271.       0,W1,"Up",76,
  272.       nop,W1+S1,nos,0,
  273.       0,W1,"4",45,
  274.       0,W1,"5",46,
  275.       0,W1,"6",47,
  276.       1,W1,"+",94);
  277.  
  278.     keyRow4 = KeyRow4(
  279.       1,C1+W1 DIV 2,"Shft",96,
  280.       0,W1,"<",48,
  281.       0,W1,"Y",49,
  282.       0,W1,"X",50,
  283.       0,W1,"C",51,
  284.       0,W1,"V",52,
  285.       0,W1,"B",53,
  286.       0,W1,"N",54,
  287.       0,W1,"M",55,
  288.       0,W1,",",56,
  289.       0,W1,".",57,
  290.       0,W1,"-",58,
  291.       1,S1+4*W1-C1-W1 DIV 2,"Shft",97,
  292.       nop,S1,nos,0,
  293.       0,W1,"Left",79,
  294.       0,W1,"Down",77,
  295.       0,W1,"Rght",78,
  296.       nop,S1,nos,0,
  297.       0,W1,"1",29,
  298.       0,W1,"2",30,
  299.       0,W1,"3",31,
  300.       1,W1,"Entr",67);
  301.  
  302.     keyRow5 = KeyRow5(
  303.       nop,S2,nos,0,
  304.       1,W2,"Alt",100,
  305.       1,W2,"LAmi",102,
  306.       0,W1*9,"Spc",64,
  307.       1,W2,"RAmi",103,
  308.       1,W2,"Alt",101,
  309.       nop,S2+S1*2+W1*3,nos,0,
  310.       0,W1*2,"0",15,
  311.       0,W1,".",60);
  312.  
  313. (*---------------------------------------------------------------------*)
  314.  
  315.   TYPE ModData = ARRAY 3,10 OF INTEGER;
  316.  
  317.   CONST
  318.     modData = ModData(
  319.  
  320.       00000U,00000U,
  321.       00000U,00000U,
  322.       00000U,00000U,
  323.       00000U,00000U,
  324.       00000U,00000U,
  325.  
  326.       060C3U,087C0U,
  327.       071CCU,06630U,
  328.       07BCCU,06630U,
  329.       06ECCU,06630U,
  330.       060C3U,087C0U,
  331.  
  332.       0F0F8U,070F0U,
  333.       0CCC0U,0D8CCU,
  334.       0CCF1U,08CCCU,
  335.       0CCC1U,0FCCCU,
  336.       0F0F9U,08CF0U);
  337.  
  338. (*---------------------------------------------------------------------*)
  339.  
  340.   TYPE IntArray136 = ARRAY 136 OF INTEGER;
  341.  
  342.   CONST Pics16Data = IntArray136(
  343.     00000U, 03800U, 00800U, 03800U, 03800U, 08400U, 03000U, 03000U,
  344.     03000U, 08400U, 0CC00U, 08C00U, 0CC00U, 0CC00U, 0CC00U, 08400U,
  345.     07000U, 0C400U, 01C00U, 00000U, 08400U, 03000U, 0E400U, 03000U,
  346.     08400U, 0C400U, 0A400U, 06400U, 00000U, 0E400U, 00000U, 03C00U,
  347.     00400U, 0F000U, 00400U, 08400U, 03C00U, 00400U, 03000U, 08400U,
  348.     00000U, 0F000U, 0E400U, 0CC00U, 09C00U, 08400U, 03000U, 08400U,
  349.     03000U, 08400U, 08400U, 03000U, 08000U, 0F000U, 08400U, 0CE74U,
  350.     08664U, 03240U, 00264U, 03270U, 08DF8U, 039F8U, 03188U, 03998U,
  351.     08C98U, 00FE0U, 02660U, 024A0U, 02460U, 00E20U, 00FF8U, 03CC0U,
  352.     01998U, 03C98U, 009C0U, 0F3C0U, 0CCC0U, 01E00U, 0CCC0U, 0C0C0U,
  353.     0F080U, 0E080U, 0C880U, 08080U, 03800U, 0F080U, 0E280U, 0CA80U,
  354.     08280U, 03800U, 05FF0U, 00000U, 05FF0U, 0FFA0U, 00000U, 0FFA0U,
  355.     0FF80U, 0FF80U, 0FF80U, 0FF80U, 0FF80U, 0FF80U, 0FF80U, 0F780U,
  356.     0C780U, 00000U, 0C7E0U, 0F7E0U, 00000U, 01000U, 07000U, 00000U,
  357.     0F000U, 00000U, 02000U, 0F000U, 09000U, 00000U, 09000U, 0F000U,
  358.     00000U, 01000U, 08000U, 0F000U, 00000U, 03000U, 03000U, 0FF9FU,
  359.     0FF0FU, 0FF9FU, 08FFFU, 03FFFU, 03C8FU, 03297U, 0888FU, 0FF9FU);
  360.  
  361. (*---------------------------------------------------------------------*)
  362.  
  363.   TYPE IntArray10 = ARRAY 10 OF INTEGER;
  364.  
  365.   CONST Pics32Data = IntArray10(
  366.     027E7U,0C000U,
  367.     02664U,04000U,
  368.     004A4U,08000U,
  369.     02464U,04000U,
  370.     02624U,0C000U);
  371.  
  372. (*---------------------------------------------------------------------*)
  373.  
  374.   TYPE IntArray28 = ARRAY 28 OF INTEGER;
  375.  
  376.   CONST ArrowData = IntArray28(
  377.     03000U, 0FF00U, 03000U, 0CF00U, 00000U, 0CF00U,
  378.     00C00U, 0FF00U, 00C00U, 0F300U, 00000U, 0F300U,
  379.     03000U, 0FC00U, 03000U, 03000U, 0CC00U, 00000U, 0CC00U, 0CC00U,
  380.     03000U, 03000U, 0FC00U, 03000U, 0CC00U, 0CC00U, 00000U, 0CC00U);
  381.  
  382. (*---------------------------------------------------------------------*)
  383.  
  384.   TYPE IntArray48 = ARRAY 48 OF INTEGER;
  385.  
  386.   CONST ZZData = IntArray48(
  387.     00000U,00000U,00600U,00940U,00F40U,030A0U,03FE0U,04010U,
  388.     07FE0U,08010U,07FF0U,09E08U,07FF8U,08404U,0FFF8U,00804U,
  389.     07FFCU,09E02U,07FFCU,080F2U,03FFEU,04020U,07FFCU,08042U,
  390.     03FFCU,040F2U,01FF8U,02004U,007F0U,01808U,001C0U,00630U,
  391.     00700U,008C0U,00FC0U,01020U,00680U,00940U,00000U,006C0U,
  392.     000C0U,00120U,000E0U,00110U,00040U,000A0U,00000U,00000U);
  393.  
  394. (*------------------------------------------------------------------------*)
  395.  
  396.   CONST
  397.     kmeIconWidth = 93;
  398.     kmeIconHeight = 30;
  399.  
  400.   TYPE IntArray360 = ARRAY 360 OF INTEGER;
  401.  
  402.   CONST KmeIconData = IntArray360(
  403.     0FDFFU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,0F828U,
  404.     0CDFEU,0AAAAU,0AAAAU,0AAAAU,0AAAEU,0C1E8U,
  405.     0FDFFU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,0C1E8U,
  406.     08000U,00000U,00000U,00000U,00000U,00008U,
  407.     0839FU,0FFFFU,0BFFFU,0FF00U,00000U,00008U,
  408.     0839FU,0FFFFU,0BFFFU,0FF00U,00000U,00008U,
  409.     08000U,00000U,00000U,00000U,00000U,00008U,
  410.     083F1U,03448U,01A24U,04CF3U,0FF3FU,0FF08U,
  411.     083E2U,04489U,09122U,040F3U,0FF3FU,0FF08U,
  412.     083F9U,0952AU,050A5U,081F0U,00014U,0AF08U,
  413.     083F8U,01224U,00C08U,013F0U,00008U,05F08U,
  414.     083FCU,06CD1U,02448U,034F0U,0281AU,01F08U,
  415.     083FCU,08912U,02244U,089F0U,00804U,0AF08U,
  416.     083F2U,00B06U,0A912U,03FF0U,0A11AU,01F08U,
  417.     083F1U,02040U,04091U,03FF0U,0CA04U,0AF08U,
  418.     080FFU,0EA24U,01225U,07FC0U,00018U,01F08U,
  419.     080FFU,08000U,00000U,0FFC0U,0000AU,08F08U,
  420.     08000U,00000U,00000U,00000U,00000U,00008U,
  421.     08000U,00000U,00000U,00000U,00000U,00008U,
  422.     08010U,00080U,00400U,00000U,00000U,00028U,
  423.     09FF0U,0FF87U,0FC00U,000FFU,0FFFFU,0FF08U,
  424.     08000U,00000U,00000U,00092U,04924U,09228U,
  425.     08000U,00000U,00000U,000FFU,0FFFFU,0FF08U,
  426.     08080U,04010U,00400U,00092U,04924U,09228U,
  427.     09F8FU,0C3F0U,0FC00U,000FFU,0FFFFU,0FF08U,
  428.     08000U,00000U,00000U,00092U,04924U,09228U,
  429.     08000U,00000U,00000U,000FFU,0FFFFU,0FF08U,
  430.     08010U,00080U,00400U,00092U,04924U,09228U,
  431.     09FF0U,0FF87U,0FC00U,000FFU,0FFFFU,0FF08U,
  432.     0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFF8U,
  433.     00000U,00000U,00000U,00000U,00000U,003C0U,
  434.     03000U,00000U,00000U,00000U,00000U,03A00U,
  435.     00000U,00000U,00000U,00000U,00000U,03A00U,
  436.     01FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFC0U,
  437.     01FFDU,0EF77U,05FDEU,0EFFFU,0FFFFU,0FFC0U,
  438.     01DEEU,0EEF7U,0FDEEU,0F7FFU,0FFFFU,0FFC0U,
  439.     01FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFC0U,
  440.     01DCEU,0CBB7U,0E5DBU,0B31DU,0A3FBU,05AC0U,
  441.     01FFDU,0BB76U,06EDDU,0BF6DU,0EFF7U,0E7C0U,
  442.     01CF6U,06AD5U,0AF5AU,07EFFU,0FFEBU,05EC0U,
  443.     01FF7U,0EDDBU,0F3F7U,0EDEFU,0FFF7U,0A7C0U,
  444.     01FBBU,0932EU,0DBB7U,0CBEFU,0D7E5U,0E7C0U,
  445.     01DDBU,076EDU,0DDBBU,076FFU,0F7FBU,05EC0U,
  446.     01EFDU,0F4F9U,056EDU,0DFEFU,05EE5U,0E3C0U,
  447.     01DEEU,0DFBFU,0BF6EU,0DFFFU,035FBU,05EC0U,
  448.     01FB5U,095DBU,0EDDAU,09DBFU,0FFE7U,0E7C0U,
  449.     01F7FU,07FFFU,0FFFFU,073BFU,0FFF5U,07EC0U,
  450.     01FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFC0U,
  451.     01FF0U,0FF87U,0FC00U,00000U,00000U,00000U,
  452.     01000U,08004U,00000U,00000U,00000U,00000U,
  453.     00000U,00000U,00000U,00000U,00000U,00000U,
  454.     00000U,00000U,00000U,00000U,00000U,00000U,
  455.     01F8FU,0C3F0U,0FC00U,00000U,00000U,00000U,
  456.     01008U,00200U,08000U,00000U,00000U,00000U,
  457.     00000U,00000U,00000U,00000U,00000U,00000U,
  458.     00000U,00000U,00000U,00000U,00000U,00000U,
  459.     01FF0U,0FF87U,0FC00U,00000U,00000U,00000U,
  460.     01000U,08004U,00000U,00000U,00000U,00000U,
  461.     00000U,00000U,00000U,00000U,00000U,00000U,
  462.     00000U,00000U,00000U,00000U,00000U,00000U);
  463.  
  464. (*------------------------------------------------------------------------*)
  465.  
  466.   CONST
  467.     kmePicWidth  = 190;
  468.     kmePicHeight =  11;
  469.  
  470.   TYPE IntArray132 = ARRAY 132 OF INTEGER;
  471.  
  472.   CONST KmePicData = IntArray132(
  473.     0F3C8U,031F0U,03FF0U,000FFU,0FFFFU,03CFFU,0FFFFU,0FFFFU,0FFFEU,007F9U,09F3FU,0FFFFU,
  474.     0F398U,084E7U,09FFFU,03CFFU,0FFFFU,039FFU,0FFFFU,0FFFFU,0FFFCU,0F3F9U,0FF3FU,0FFFFU,
  475.     0E673U,09C9FU,0FFFEU,0780FU,00FFEU,067C3U,09E06U,07810U,03FF3U,0FE03U,03C0EU,00C07U,
  476.     0E4F3U,09C9FU,0FFFEU,078E6U,067FEU,04F99U,0CE00U,033C3U,09FF3U,0FCE3U,03E7CU,0E473U,
  477.     0C1E7U,03907U,0807CU,0F3E1U,09FFCU,01E67U,0CC33U,00F87U,09FE0U,0F3E6U,07CF3U,0E1FFU,
  478.     0C4E7U,0393FU,0FFFCU,0F3E1U,03FFCU,04E4FU,0E433U,00F87U,09FE7U,0F3E6U,07CF3U,0E1FFU,
  479.     09CCEU,0727FU,0FFF9U,0E7C0U,0E7F9U,0CC39U,0E066U,01F0FU,03FCFU,0E7CCU,0F9E7U,0C3FFU,
  480.     09E4EU,0733CU,0FFF9U,0E7C9U,0CFF9U,0E673U,0F066U,04E0EU,07FE7U,0939CU,0F9F3U,093FFU,
  481.     03E1CU,0E703U,0FFF3U,0CF98U,03FF3U,0E60CU,0F0CCU,0C001U,0FFE0U,07079U,0F3F0U,067FFU,
  482.     0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,067FFU,0FF9FU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,
  483.     0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,01FFFU,0FFBFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU);
  484.  
  485. (*------------------------------------------------------------------------*)
  486.  
  487.   PROCEDURE Busy(win: I.WindowPtr);
  488.   BEGIN
  489.     I.SetPointer(win,zz^,22,16,-7,-8);
  490.   END Busy;
  491.  
  492. (*------------------------------------------------------------------------*)
  493.  
  494.   PROCEDURE FindGadget(id: INTEGER): I.GadgetPtr;
  495.     VAR i: INTEGER;
  496.   BEGIN
  497.     i := 0;
  498.     WHILE i < gadCnt DO
  499.       IF gad[i].gadgetID = id THEN RETURN s.ADR(gad[i]) END;
  500.       INC(i);
  501.     END;
  502.     (* $IF debug *)
  503.     io.WriteString("'FindGadget' failed\n");
  504.     (* $END *)
  505.     HALT(0);
  506.   END FindGadget;
  507.  
  508. (*---------------------------------------------------------------------*)
  509.  
  510.   PROCEDURE PutImage(rp               : g.RastPortPtr;
  511.                      x,y,width,height : INTEGER;
  512.                      data             : e.ADDRESS;
  513.                      mode             : INTEGER);
  514.     VAR
  515.       img: I.Image;
  516.       dat: g.PLANEPTR;
  517.  
  518.   BEGIN
  519.     dat := data;
  520.     e.CopyMem(dat^,chipBuf^,s.SIZE(chipBuf^));
  521.     img.leftEdge := 6;
  522.     img.topEdge := 1;
  523.     img.width := width;
  524.     img.height := height;
  525.     IF mode < 2 THEN
  526.       img.depth := 1;
  527.     ELSE
  528.       img.depth := 2;
  529.     END;
  530.     img.imageData := chipBuf;
  531.     CASE mode OF
  532.     | 0:
  533.       img.planePick := SHORTSET{0};
  534.       img.planeOnOff := SHORTSET{};
  535.     | 1:
  536.       img.planePick := SHORTSET{1};
  537.       img.planeOnOff := SHORTSET{0};
  538.     ELSE
  539.       img.planePick := SHORTSET{0,1};
  540.       img.planeOnOff := SHORTSET{0};
  541.     END;
  542.     img.nextImage := NIL;
  543.     I.DrawImage(rp,img,x,y);
  544.   END PutImage;
  545.  
  546. (*---------------------------------------------------------------------*)
  547.  
  548.   PROCEDURE AsciiToRaw(VAR s1,s2: String);
  549.  
  550.     VAR i,j,l,n,z : INTEGER;
  551.         state     : INTEGER;
  552.         ch        : CHAR;
  553.  
  554.     PROCEDURE AddChar(ch: CHAR);
  555.     BEGIN
  556.       IF j < strLen THEN
  557.         s2[j] := ch;
  558.         INC(j);
  559.       END;
  560.     END AddChar;
  561.  
  562.     PROCEDURE Hex2Dez(ch: CHAR; VAR z: INTEGER): BOOLEAN;
  563.     BEGIN
  564.       IF (ch >= "0") & (ch <= "9") THEN
  565.         z := ORD(ch) - ORD("0");
  566.         RETURN TRUE;
  567.       END;
  568.       ch := CAP(ch);
  569.       IF (ch >= "A") & (ch <= "F") THEN
  570.         z := 10 + (ORD(ch) - ORD("A"));
  571.         RETURN TRUE;
  572.       END;
  573.       RETURN FALSE;
  574.     END Hex2Dez;
  575.  
  576.   BEGIN  (* AsciiToRaw *)
  577.     state := 0;
  578.     l := st.Length(s1);
  579.     j := 0;
  580.     i := 0; WHILE i <= l DO
  581.       IF i < l THEN
  582.         ch := s1[i]
  583.       ELSE
  584.         ch := 0X
  585.       END;
  586.       CASE state OF
  587.       | 0:
  588.         IF ch = "\\" THEN
  589.           state := 1;
  590.         ELSE
  591.           AddChar(ch);
  592.         END;
  593.       | 1:
  594.         CASE ch OF
  595.         | "n": AddChar(0AX); state := 0
  596.         | "r": AddChar(0DX); state := 0
  597.         | "e": AddChar(1BX); state := 0
  598.         | "[": AddChar(9BX); state := 0
  599.         | "o": AddChar(00X); state := 0
  600.         | "t": AddChar(09X); state := 0
  601.         | "b": AddChar(08X); state := 0
  602.         | "f": AddChar(0CX); state := 0
  603.         | "x": state := 2; n := 0;
  604.         ELSE
  605.           AddChar(ch);
  606.           state := 0;
  607.         END;
  608.       | 2,3:
  609.         IF Hex2Dez(ch,z) THEN
  610.           n := n * 16 + z;
  611.           INC(state);
  612.         ELSE
  613.           AddChar(CHR(n));
  614.           state := 0;
  615.           DEC(i);
  616.         END;
  617.       | 4:
  618.         state := 0;
  619.         AddChar(CHR(n));
  620.         DEC(i);
  621.       END;
  622.     INC(i) END;
  623.     AddChar(0X);
  624.     s2[strLen-1] := 0X
  625.   END AsciiToRaw;
  626.  
  627. (*---------------------------------------------------------------------*)
  628.  
  629.   PROCEDURE RawToAscii(VAR s1,s2: String; hex: BOOLEAN);
  630.  
  631.     CONST
  632.       hexStr = "0123456789ABCDEF";
  633.  
  634.     VAR
  635.       i,j,l   : INTEGER;
  636.       ch      : CHAR;
  637.       ctrl    : BOOLEAN;
  638.  
  639.     PROCEDURE AddChar(ch: CHAR);
  640.     BEGIN
  641.       IF j < strLen THEN
  642.         s2[j] := ch;
  643.         INC(j);
  644.       END;
  645.     END AddChar;
  646.  
  647.     PROCEDURE AddHex(ch: CHAR);
  648.     BEGIN
  649.       AddChar(hexStr[ORD(ch) DIV 16]);
  650.       AddChar(hexStr[ORD(ch) MOD 16]);
  651.     END AddHex;
  652.  
  653.   BEGIN
  654.     l := st.Length(s1);
  655.     j := 0;
  656.     i := 0; WHILE i < l DO
  657.       ch := s1[i];
  658.       ctrl := ((ORD(ch) MOD 128) < 32) OR hex;
  659.       IF ctrl THEN
  660.         AddChar("\\");
  661.         IF hex THEN
  662.           AddChar("x"); AddHex(ch);
  663.         ELSE
  664.           CASE ch OF
  665.           | 0AX: AddChar("n")
  666.           | 1BX: AddChar("e")
  667.           | 0DX: AddChar("r")
  668.           | 09X: AddChar("t")
  669.           | 9BX: AddChar("[")
  670.           | 08X: AddChar("b")
  671.           | 0CX: AddChar("f")
  672.           ELSE
  673.             AddChar("x"); AddHex(ch);
  674.           END;
  675.         END;
  676.       ELSE
  677.         AddChar(ch);
  678.         IF ch = "\\" THEN AddChar("\\") END;
  679.       END;
  680.     INC(i) END;
  681.     AddChar(0X);
  682.     s2[strLen-1] := 0X
  683.   END RawToAscii;
  684.  
  685. (*---------------------------------------------------------------------*)
  686.  
  687.   PROCEDURE DrawKey(key: Key; x,y: INTEGER);
  688.     VAR dummy,height,z : INTEGER;
  689.   BEGIN
  690.     g.SetDrMd(rp,g.jam2);
  691.     height := keyHeight;
  692.     IF (key.name="Entr") OR (key.name="Rtrn") THEN INC(height,height) END;
  693.     g.SetAPen(rp,1); g.SetBPen(rp,1);
  694.     g.RectFill(rp,x,y-1,x+key.width-1,y+height-1);
  695.     IF key.type = white THEN
  696.       g.SetAPen(rp,1); g.SetBPen(rp,2);
  697.     ELSE
  698.       g.SetAPen(rp,1); g.SetBPen(rp,3);
  699.     END;
  700.     g.RectFill(rp,x+1,y,x+key.width-2,y+height-2);
  701.     IF key.type = white THEN
  702.       g.SetAPen(rp,2); g.SetBPen(rp,2);
  703.     ELSE
  704.       g.SetAPen(rp,3) ; g.SetBPen(rp,3);
  705.     END;
  706.     g.RectFill(rp,x+5,y,x+key.width-6,y+height-5);
  707.     IF st.Length(key.name) = 1 THEN
  708.       g.SetAPen(rp,1); g.SetDrMd(rp,g.jam1); g.Move(rp,x+6,y+7);
  709.       g.Text(rp,key.name,1);
  710.     ELSE
  711.       IF    key.name="Alt"  THEN PutImage(rp,x,y,14,5,s.ADR(Pics16Data[55]),1);
  712.       ELSIF key.name="LAmi" THEN PutImage(rp,x,y,9,5,s.ADR(Pics16Data[80]),1);
  713.       ELSIF key.name="RAmi" THEN PutImage(rp,x,y,9,5,s.ADR(Pics16Data[85]),1);
  714.       ELSIF key.name="Ctrl" THEN PutImage(rp,x,y,15,5,s.ADR(Pics16Data[60]),1);
  715.       ELSIF key.name="Caps" THEN PutImage(rp,x,y-1,13,9,s.ADR(Pics16Data[127]),1);
  716.       ELSIF key.name="Esc"  THEN PutImage(rp,x,y,13,5,s.ADR(Pics16Data[70]),1);
  717.       ELSIF key.name="Help" THEN PutImage(rp,x,y,18,5,s.ADR(Pics32Data[0]),1);
  718.       ELSIF key.name="Del"  THEN PutImage(rp,x,y,13,5,s.ADR(Pics16Data[65]),1);
  719.       ELSIF key.name="Shft" THEN PutImage(rp,x,y,10,5,s.ADR(Pics16Data[75]),1);
  720.       ELSIF key.name="Rtrn" THEN PutImage(rp,x+6,y+8,11,12,s.ADR(Pics16Data[96]),1);
  721.       ELSIF key.name="Tab"  THEN PutImage(rp,x,y,12,6,s.ADR(Pics16Data[90]),1);
  722.       ELSIF key.name="Left" THEN PutImage(rp,x,y,8,3,s.ADR(ArrowData[0]),2);
  723.       ELSIF key.name="Rght" THEN PutImage(rp,x,y,8,3,s.ADR(ArrowData[6]),2);
  724.       ELSIF key.name="Up"   THEN PutImage(rp,x,y,6,4,s.ADR(ArrowData[12]),2);
  725.       ELSIF key.name="Down" THEN PutImage(rp,x,y,6,4,s.ADR(ArrowData[20]),2);
  726.       ELSIF key.name="Bs"   THEN PutImage(rp,x,y,8,3,s.ADR(ArrowData[3]),1);
  727.       ELSIF key.name="Entr" THEN PutImage(rp,x+2,y,4,19,s.ADR(Pics16Data[108]),1);
  728.       ELSIF key.name[0]="f" THEN
  729.         PutImage(rp,x,y,5,5,s.ADR(Pics16Data[0]),1);
  730.         z := ORD(key.name[1]) - ORD("0");
  731.         IF z = 0 THEN (* F10 *)
  732.           PutImage(rp,x+6,y,6,5,s.ADR(Pics16Data[10]),1);
  733.           PutImage(rp,x+12,y,6,5,s.ADR(Pics16Data[(z+1)*5]),1);
  734.         ELSE          (* F1 - F9 *)
  735.           PutImage(rp,x+6,y,6,5,s.ADR(Pics16Data[(z+1)*5]),1);
  736.         END;
  737.       END;
  738.     END;
  739.     IF makeGads THEN
  740.       gad[gadCnt].leftEdge := x+5;
  741.       gad[gadCnt].topEdge := y;
  742.       gad[gadCnt].width := key.width-6-5+1;
  743.       gad[gadCnt].height := height-5+1;
  744.       gad[gadCnt].gadgetType := I.boolGadget;
  745.       gad[gadCnt].activation := {I.relVerify,I.toggleSelect};
  746.       gad[gadCnt].gadgetID := idKey;
  747.       gad[gadCnt].flags := {};
  748.       gad[gadCnt].gadgetRender := NIL;
  749.       gad[gadCnt].selectRender := NIL;
  750.       gad[gadCnt].gadgetText := NIL;
  751.       gad[gadCnt].specialInfo := NIL;
  752.       gad[gadCnt].mutualExclude := LONGSET{};
  753.       gad[gadCnt].nextGadget := NIL;
  754.       gad[gadCnt].userData := key.code;
  755.     END;
  756.     dummy := I.AddGadget(win,gad[gadCnt],-1);
  757.     INC(gadCnt);
  758.   END DrawKey;
  759.  
  760. (*---------------------------------------------------------------------*)
  761.  
  762.   PROCEDURE DrawKeyRow(key: ARRAY OF Key; y: INTEGER); (* CopyArrays- *)
  763.     VAR i : INTEGER;
  764.         x : INTEGER;
  765.   BEGIN
  766.     x := 36;
  767.     i := 0; WHILE i < LEN(key) DO
  768.       IF key[i].type # nop THEN DrawKey(key[i],x,y) END;
  769.       INC(x,key[i].width);
  770.     INC(i) END;
  771.   END DrawKeyRow;
  772.  
  773. (*---------------------------------------------------------------------*)
  774.  
  775.   PROCEDURE MakeGadget(x,y : INTEGER;
  776.                        txt : ARRAY OF CHAR;
  777.                        id  : INTEGER);       (* $CopyArrays- *)
  778.     VAR
  779.       w,h : INTEGER;
  780.  
  781.   BEGIN
  782.     w := LEN(txt)*8; h := 12;
  783.     IF txt[0] = 0X THEN w := 40; h := 9 END;
  784.     g.SetDrMd(rp,g.jam1); g.SetAPen(rp,1);
  785.     g.Move(rp,x+4,y+8); g.Text(rp,txt,LEN(txt)-1);
  786.     g.SetAPen(rp,2);
  787.     g.Move(rp,x+1,y+h-2); g.Draw(rp,x+1,y); g.Draw(rp,x+w-2,y);
  788.     g.Move(rp,x,y); g.Draw(rp,x,y+h-1);
  789.     g.SetAPen(rp,1);
  790.     g.Move(rp,x+1,y+h-1); g.Draw(rp,x+w-2,y+h-1); g.Draw(rp,x+w-2,y+1);
  791.     g.Move(rp,x+w-1,y); g.Draw(rp,x+w-1,y+h-1);
  792.     IF makeGads THEN
  793.       gad[gadCnt].leftEdge := x;
  794.       gad[gadCnt].topEdge := y;
  795.       gad[gadCnt].width := w;
  796.       gad[gadCnt].height := h;
  797.       gad[gadCnt].gadgetType := I.boolGadget;
  798.       IF id >= 200 THEN
  799.         gad[gadCnt].activation := {I.relVerify,I.toggleSelect};
  800.       ELSE
  801.         gad[gadCnt].activation := {I.relVerify};
  802.       END;
  803.       gad[gadCnt].gadgetID := id;
  804.       gad[gadCnt].flags := {};
  805.       gad[gadCnt].gadgetRender := NIL;
  806.       gad[gadCnt].selectRender := NIL;
  807.       gad[gadCnt].gadgetText := NIL;
  808.       gad[gadCnt].specialInfo := NIL;
  809.       gad[gadCnt].mutualExclude := LONGSET{};
  810.       gad[gadCnt].nextGadget := NIL;
  811.       gad[gadCnt].userData := NIL;
  812.     END;
  813.     dummy := I.AddGadget(win,gad[gadCnt],-1);
  814.     INC(gadCnt);
  815.   END MakeGadget;
  816.  
  817. (*---------------------------------------------------------------------*)
  818.  
  819.   PROCEDURE MakeStrGadget(x,y,w,id:INTEGER);
  820.   BEGIN
  821.     g.SetAPen(rp,1);
  822.     g.Move(rp,x,y+8);
  823.     g.Draw(rp,x+w,y+8);
  824.  
  825.     IF makeGads THEN
  826.  
  827.       buffer[strCnt,0] := 0X;
  828.  
  829.       strInf[strCnt].buffer := s.ADR(buffer[strCnt]);
  830.       strInf[strCnt].undoBuffer := s.ADR(undobf[strCnt]);
  831.       strInf[strCnt].maxChars := strLen;
  832.  
  833.       gad[gadCnt].leftEdge := x;
  834.       gad[gadCnt].topEdge := y;
  835.       gad[gadCnt].width := w;
  836.       gad[gadCnt].height := 8;
  837.       gad[gadCnt].gadgetType := I.strGadget;
  838.       gad[gadCnt].activation := {I.relVerify};
  839.       gad[gadCnt].gadgetID := id;
  840.       gad[gadCnt].flags := {};
  841.       gad[gadCnt].gadgetRender := NIL;
  842.       gad[gadCnt].selectRender := NIL;
  843.       gad[gadCnt].gadgetText := NIL;
  844.       gad[gadCnt].specialInfo := s.ADR(strInf[strCnt]);
  845.       gad[gadCnt].mutualExclude := LONGSET{};
  846.       gad[gadCnt].nextGadget := NIL;
  847.       gad[gadCnt].userData := NIL;
  848.     END;
  849.     dummy := I.AddGadget(win,gad[gadCnt],-1);
  850.     INC(gadCnt);
  851.     INC(strCnt);
  852.   END MakeStrGadget;
  853.  
  854. (*---------------------------------------------------------------------*)
  855.  
  856.   PROCEDURE NumQual(type: SHORTSET): INTEGER;
  857.     VAR n: INTEGER;
  858.         deskr: BOOLEAN;
  859.   BEGIN
  860.     n := 1;
  861.     IF km.alt     IN type THEN INC(n,n) END;
  862.     IF km.shift   IN type THEN INC(n,n) END;
  863.     IF km.control IN type THEN INC(n,n) END;
  864.     IF km.nop IN type THEN n := 0 END;
  865.     deskr := (km.string IN type) OR (km.dead IN type);
  866.     IF ~deskr & (n > 4) THEN n := 4 END;
  867.     RETURN n
  868.   END NumQual;
  869.  
  870. (*---------------------------------------------------------------------*)
  871.  
  872.   PROCEDURE SetModGads;
  873.     VAR i: INTEGER; gad: I.GadgetPtr;
  874.   BEGIN
  875.     i := 0; WHILE i < 8 DO
  876.       gad := FindGadget(idMod+i);
  877.       PutImage(rp,gad.leftEdge-1,gad.topEdge+1,30,5,s.ADR(modData[gad.userData]),0);
  878.     INC(i) END;
  879.   END SetModGads;
  880.  
  881. (*---------------------------------------------------------------------*)
  882.  
  883.   PROCEDURE SetStrGads(type : SHORTSET);
  884.  
  885.     TYPE Tab = ARRAY 8,8 OF SHORTINT;
  886.  
  887.     CONST
  888.       tab  = Tab (0,0,0,0,0,0,0,0,
  889.                   0,1,0,0,0,0,0,0,
  890.                   0,2,0,0,0,0,0,0,
  891.                   0,1,2,3,0,0,0,0,
  892.                   0,4,0,0,0,0,0,0,
  893.                   0,1,4,5,0,0,0,0,
  894.                   0,2,4,6,0,0,0,0,
  895.                   0,1,2,3,4,5,6,7);
  896.     VAR
  897.       i,n : INTEGER;
  898.       gad: I.GadgetPtr;
  899.       qual : SHORTINT;
  900.       qualStr : ARRAY 16 OF CHAR;
  901.  
  902.     PROCEDURE QualString(VAR qualStr : ARRAY OF CHAR; i: INTEGER);
  903.       VAR l : INTEGER;
  904.           q : SHORTSET;
  905.     BEGIN
  906.       qualStr := nos;
  907.       q := s.VAL(SHORTSET,SHORT(i));
  908.       IF km.shift   IN q THEN st.Append(qualStr,"SHFT+") END;
  909.       IF km.alt     IN q THEN st.Append(qualStr,"ALT+") END;
  910.       IF km.control IN q THEN st.Append(qualStr,"CTRL+") END;
  911.       l := st.Length(qualStr);
  912.       IF (l > 0) & (qualStr[l-1] = "+") THEN
  913.         st.Delete(qualStr,l-1,1);
  914.       END;
  915.     END QualString;
  916.  
  917.   BEGIN
  918.     g.SetDrMd(rp,g.jam2);
  919.     g.SetAPen(rp,1); g.SetBPen(rp,0);
  920.     n := NumQual(type);
  921.     qual := s.VAL(SHORTINT,type * SHORTSET{0,1,2});
  922.     i := 0; WHILE i < 8 DO
  923.       g.Move(rp,265+X2,i*10+113+Y1); g.Text(rp,"             ",13);
  924.       gad := FindGadget(idStr+i);
  925.       IF i < n THEN
  926.         QualString(qualStr,tab[qual,i]);
  927.         g.Move(rp,265+X2+(13-st.Length(qualStr))*8,i*10+113+Y1);
  928.         g.Text(rp,qualStr,st.Length(qualStr));
  929.         EXCL(gad.flags,I.gadgDisabled);
  930.       ELSE
  931.         INCL(gad.flags,I.gadgDisabled);
  932.       END;
  933.     INC(i) END;
  934.     I.RefreshGList(FindGadget(idStr),win,NIL,8);
  935.   END SetStrGads;
  936.  
  937. (*---------------------------------------------------------------------*)
  938.  
  939.   PROCEDURE ClearGadgets;
  940.     VAR i: INTEGER;
  941.         gadget:I.GadgetPtr;
  942.   BEGIN
  943.     I.RefreshGList(FindGadget(idShift),win,NIL,9);
  944.     gadget := FindGadget(idShift);   EXCL(gadget.flags,I.selected);
  945.     gadget := FindGadget(idAlt);     EXCL(gadget.flags,I.selected);
  946.     gadget := FindGadget(idControl); EXCL(gadget.flags,I.selected);
  947.     gadget := FindGadget(idDownup);  EXCL(gadget.flags,I.selected);
  948.     gadget := FindGadget(idString);  EXCL(gadget.flags,I.selected);
  949.     gadget := FindGadget(idDead);    EXCL(gadget.flags,I.selected);
  950.     gadget := FindGadget(idNop);     EXCL(gadget.flags,I.selected);
  951.     gadget := FindGadget(idCapsable);   EXCL(gadget.flags,I.selected);
  952.     gadget := FindGadget(idRepeatable); EXCL(gadget.flags,I.selected);
  953.     IF lastKeyGad # NIL THEN
  954.       INCL(lastKeyGad.flags,I.selected);
  955.       I.RefreshGList(lastKeyGad,win,NIL,1);
  956.       EXCL(lastKeyGad.flags,I.selected);
  957.     END;
  958.     i := 0; WHILE i < 8 DO
  959.       buffer[i,0] := 0X;
  960.       gadget := FindGadget(idMod+i);
  961.       gadget.userData := 0;
  962.     INC(i) END;
  963.     SetStrGads(SHORTSET{});
  964.     SetModGads;
  965.     lastKeyGad := NIL;
  966.     rawCode := -1;
  967.     keyModified := FALSE;
  968.   END ClearGadgets;
  969.  
  970. (*---------------------------------------------------------------------*)
  971.  
  972.   PROCEDURE SetType(type: SHORTSET);
  973.  
  974.     PROCEDURE Select(id,flag:INTEGER);
  975.       VAR gad : I.GadgetPtr;
  976.     BEGIN
  977.       gad := FindGadget(id);
  978.       IF flag IN type THEN
  979.         INCL(gad.flags,I.selected)
  980.       ELSE
  981.         EXCL(gad.flags,I.selected)
  982.       END;
  983.     END Select;
  984.  
  985.   BEGIN
  986.     I.RefreshGList(FindGadget(idShift),win,NIL,7);
  987.     Select(idShift,km.shift);
  988.     Select(idAlt,km.alt);
  989.     Select(idControl,km.control);
  990.     Select(idNop,km.nop);
  991.     Select(idDead,km.dead);
  992.     Select(idString,km.string);
  993.     Select(idDownup,km.downup);
  994.     I.RefreshGList(FindGadget(idShift),win,NIL,7);
  995.   END SetType;
  996.  
  997. (*---------------------------------------------------------------------*)
  998.  
  999.   PROCEDURE GetType(VAR type: SHORTSET);
  1000.  
  1001.     PROCEDURE Select(id,flag:INTEGER);
  1002.       VAR gad : I.GadgetPtr;
  1003.     BEGIN
  1004.       gad := FindGadget(id);
  1005.       IF I.selected IN gad.flags THEN INCL(type,flag) END;
  1006.     END Select;
  1007.  
  1008.   BEGIN
  1009.     type := SHORTSET{};
  1010.     Select(idShift,km.shift);
  1011.     Select(idAlt,km.alt);
  1012.     Select(idControl,km.control);
  1013.     Select(idNop,km.nop);
  1014.     Select(idDead,km.dead);
  1015.     Select(idString,km.string);
  1016.     Select(idDownup,km.downup);
  1017.   END GetType;
  1018.  
  1019. (*---------------------------------------------------------------------*)
  1020.  
  1021.   PROCEDURE New(VAR adr: e.ADDRESS; size : LONGINT);
  1022.   BEGIN
  1023.     IF size <= 0 THEN size := 1 END;
  1024.     LOOP
  1025.       ol.New(adr,size);
  1026.       IF adr # NIL THEN RETURN END;
  1027.       IF ~rq.Request(kmr,oom,rtry,cncl) THEN HALT(0) END;
  1028.     END;
  1029.   END New;
  1030.  
  1031. (*---------------------------------------------------------------------*)
  1032.  
  1033.   PROCEDURE IntToByte(i: INTEGER): BYTE;
  1034.   BEGIN
  1035.     rq.Assert((i >= 0) & (i < 256),"Range Error");
  1036.     (* $RangeChk- *)
  1037.     RETURN SHORT(i);
  1038.     (* $RangeChk= *)
  1039.   END IntToByte;
  1040.  
  1041. (*---------------------------------------------------------------------*)
  1042.  
  1043.   PROCEDURE GetKey(code : INTEGER);
  1044.  
  1045.     VAR
  1046.       strDeskr    : StrDeskrPtr;
  1047.       deadDeskr   : DeadDeskrPtr;
  1048.       deadType    : SHORTINT;
  1049.       charPtr     : e.STRPTR;
  1050.       i,len       : INTEGER;
  1051.       gadget      : I.GadgetPtr;
  1052.       type        : SHORTSET;
  1053.       keyInfo     : Str4;
  1054.       code64      : INTEGER;
  1055.       kmap        : KeyMapPtr;
  1056.  
  1057.   BEGIN
  1058.     IF (code < 0) OR (keyMap = NIL)  THEN RETURN END;
  1059.     code64 := code MOD 64;
  1060.     IF code >= 64 THEN
  1061.       kmap := s.ADR(keyMap.hiKeyMapTypes)
  1062.     ELSE
  1063.       kmap := s.ADR(keyMap.loKeyMapTypes)
  1064.     END;
  1065.  
  1066.     type := kmap.loKeyMapTypes^[code64];
  1067.     SetType(type);
  1068.  
  1069.     gadget := FindGadget(idCapsable);
  1070.     I.RefreshGList(gadget,win,NIL,2);
  1071.     IF (code64 MOD 8) IN kmap.loCapsable^[code64 DIV 8] THEN
  1072.       INCL(gadget.flags,I.selected)
  1073.     ELSE
  1074.       EXCL(gadget.flags,I.selected)
  1075.     END;
  1076.  
  1077.     gadget := FindGadget(idRepeatable);
  1078.     IF (code64 MOD 8) IN kmap.loRepeatable^[code64 DIV 8] THEN
  1079.       INCL(gadget.flags,I.selected)
  1080.     ELSE
  1081.       EXCL(gadget.flags,I.selected)
  1082.     END;
  1083.  
  1084.     gadget := FindGadget(idCapsable);
  1085.     I.RefreshGList(gadget,win,NIL,2);
  1086.  
  1087.     SetStrGads(type);
  1088.  
  1089.     i := 0; WHILE i < 8 DO
  1090.       gadget := FindGadget(idMod+i);
  1091.       gadget.userData := 0;
  1092.     INC(i) END;
  1093.  
  1094.     IF km.string IN type THEN
  1095.       strDeskr := kmap.loKeyMap^[code64];
  1096.       i := 0; WHILE i < NumQual(type) DO
  1097.         charPtr := s.VAL(LONGINT,strDeskr) + ORD(s.VAL(BYTE,strDeskr^[i].offs));
  1098.         len := ORD(s.VAL(BYTE,strDeskr^[i].len));
  1099.         IF len >= strLen THEN len := strLen - 1 END;
  1100.         IF len > 0 THEN
  1101.           e.CopyMem(charPtr^,string,len);
  1102.         END;
  1103.         string[len] := 0X;
  1104.         RawToAscii(string,buffer[i],FALSE);
  1105.       INC(i) END;
  1106.       WHILE i < 8 DO
  1107.         buffer[i,0] := 0X;
  1108.       INC(i) END;
  1109.  
  1110.     ELSIF km.dead IN type THEN
  1111.  
  1112.       deadDeskr := kmap.loKeyMap^[code64];
  1113.  
  1114.       i := 0; WHILE i < NumQual(type) DO
  1115.         gadget := FindGadget(idMod+i);
  1116.         deadType := deadDeskr^[i].type;
  1117.         CASE deadType OF
  1118.         | 0:
  1119.           gadget.userData := 0;
  1120.           string[0] := CHR(deadDeskr^[i].val);
  1121.           string[1] := 0X;
  1122.           RawToAscii(string,buffer[i],FALSE);
  1123.  
  1124.         | 1: (* mod *)
  1125.           gadget.userData := 1;
  1126.           charPtr := s.VAL(LONGINT,deadDeskr) + ORD(s.VAL(BYTE,deadDeskr^[i].val));
  1127.           len := deadLen;
  1128.           IF len >= strLen THEN len := strLen - 1 END;
  1129.           IF len > 0 THEN
  1130.             e.CopyMem(charPtr^,string,len);
  1131.           END;
  1132.           string[len] := 0X;
  1133.           RawToAscii(string,buffer[i],FALSE);
  1134.  
  1135.         | 8: (* dead *)
  1136.           gadget.userData := 2;
  1137.           string[0] := CHR(deadDeskr^[i].val);
  1138.           string[1] := 0X;
  1139.           RawToAscii(string,buffer[i],TRUE);
  1140.  
  1141.         ELSE
  1142.         END;
  1143.       INC(i) END;
  1144.  
  1145.       WHILE i < 8 DO
  1146.         buffer[i,0] := 0X;
  1147.       INC(i) END;
  1148.  
  1149.     ELSE
  1150.  
  1151.       keyInfo := s.VAL(Str4,kmap.loKeyMap^[code64]);
  1152.       i := 0; WHILE i < NumQual(type) DO
  1153.         string[0] := keyInfo[3-i];
  1154.         string[1] := 0X;
  1155.         RawToAscii(string,buffer[i],FALSE);
  1156.       INC(i) END;
  1157.       WHILE i < 8 DO
  1158.         buffer[i,0] := 0X;
  1159.       INC(i) END;
  1160.     END;
  1161.  
  1162.     SetModGads;
  1163.     I.RefreshGList(FindGadget(idStr),win,NIL,8);
  1164.  
  1165.   END GetKey;
  1166.  
  1167. (*---------------------------------------------------------------------*)
  1168.  
  1169.   PROCEDURE SetKey(code: INTEGER);
  1170.  
  1171.     VAR
  1172.       strDeskr    : StrDeskrPtr;
  1173.       deadDeskr   : DeadDeskrPtr;
  1174.       deadType    : SHORTINT;
  1175.       charPtr     : e.STRPTR;
  1176.       i,len       : INTEGER;
  1177.       size,offset : INTEGER;
  1178.       gadget      : I.GadgetPtr;
  1179.       type        : SHORTSET;
  1180.       keyInfo     : Str4;
  1181.       code64      : INTEGER;
  1182.       kmap        : KeyMapPtr;
  1183.  
  1184.   BEGIN
  1185.     IF (code < 0) OR (keyMap = NIL) THEN RETURN END;
  1186.  
  1187.     mapModified := TRUE;
  1188.  
  1189.     code64 := code MOD 64;
  1190.     IF code >= 64 THEN
  1191.       kmap := s.ADR(keyMap.hiKeyMapTypes)
  1192.     ELSE
  1193.       kmap := s.ADR(keyMap.loKeyMapTypes)
  1194.     END;
  1195.  
  1196.     GetType(type);
  1197.     kmap.loKeyMapTypes^[code64] := type;
  1198.  
  1199.     gadget := FindGadget(idCapsable);
  1200.     IF I.selected IN gadget.flags THEN
  1201.       INCL(kmap.loCapsable^[code64 DIV 8],code64 MOD 8)
  1202.     ELSE
  1203.       EXCL(kmap.loCapsable^[code64 DIV 8],code64 MOD 8)
  1204.     END;
  1205.  
  1206.     gadget := FindGadget(idRepeatable);
  1207.     IF I.selected IN gadget.flags THEN
  1208.       INCL(kmap.loRepeatable^[code64 DIV 8],code64 MOD 8)
  1209.     ELSE
  1210.       EXCL(kmap.loRepeatable^[code64 DIV 8],code64 MOD 8)
  1211.     END;
  1212.  
  1213.     IF km.string IN type THEN
  1214.  
  1215.       size := 0;
  1216.       i := 0; WHILE i < NumQual(type) DO
  1217.         INC(size,2);
  1218.         AsciiToRaw(buffer[i],string);
  1219.         INC(size,st.Length(string));
  1220.       INC(i) END;
  1221.  
  1222.       New(strDeskr,size);
  1223.  
  1224.       offset := NumQual(type) * 2;
  1225.       i := 0; WHILE i < NumQual(type) DO
  1226.         AsciiToRaw(buffer[i],string);
  1227.         charPtr := s.VAL(LONGINT,strDeskr) + offset;
  1228.         len := st.Length(string);
  1229.         IF len > 0 THEN
  1230.           e.CopyMem(string,charPtr^,len);
  1231.         END;
  1232.         strDeskr^[i].len := IntToByte(len);
  1233.         strDeskr^[i].offs := IntToByte(offset);
  1234.         INC(offset,st.Length(string));
  1235.       INC(i) END;
  1236.  
  1237.       kmap.loKeyMap^[code64] := strDeskr;
  1238.  
  1239.     ELSIF km.dead IN type THEN
  1240.  
  1241.       size := 0;
  1242.       i := 0; WHILE i < NumQual(type) DO
  1243.         gadget := FindGadget(idMod + i);
  1244.         INC(size,2);
  1245.         IF gadget.userData = 1 THEN
  1246.           INC(size,deadLen)
  1247.         END;
  1248.       INC(i) END;
  1249.  
  1250.       New(deadDeskr,size);
  1251.  
  1252.       offset := NumQual(type) * 2;
  1253.  
  1254.       i := 0; WHILE i < NumQual(type) DO
  1255.  
  1256.         AsciiToRaw(buffer[i],string);
  1257.         gadget := FindGadget(idMod + i);
  1258.  
  1259.         CASE gadget.userData OF
  1260.         | 0:
  1261.           deadDeskr^[i].type := 0;
  1262.           deadDeskr^[i].val := s.VAL(BYTE,string[0]);
  1263.  
  1264.         | 1:
  1265.           deadDeskr^[i].type := 1;
  1266.           deadDeskr^[i].val := IntToByte(offset);
  1267.           charPtr := s.VAL(LONGINT,deadDeskr) + offset;
  1268.           IF deadLen > 0 THEN
  1269.             e.CopyMem(string,charPtr^,deadLen);
  1270.           END;
  1271.           INC(offset,deadLen);
  1272.  
  1273.         | 2:
  1274.           deadDeskr^[i].type := 8;
  1275.           deadDeskr^[i].val := s.VAL(BYTE,string[0]);
  1276.         END;
  1277.  
  1278.       INC(i) END;
  1279.  
  1280.       kmap.loKeyMap^[code64] := deadDeskr;
  1281.  
  1282.     ELSE
  1283.  
  1284.       i := 0; WHILE i < NumQual(type) DO
  1285.         AsciiToRaw(buffer[i],string);
  1286.         keyInfo[3-i] := string[0];
  1287.       INC(i) END;
  1288.       WHILE i < 4 DO
  1289.         keyInfo[3-i] := 0X;
  1290.       INC(i) END;
  1291.       kmap.loKeyMap^[code64] := s.VAL(LONGINT,keyInfo);
  1292.  
  1293.     END;
  1294.  
  1295.   END SetKey;
  1296.  
  1297. (*---------------------------------------------------------------------*)
  1298.  
  1299.   PROCEDURE PushRelo(offs: LONGINT);
  1300.   BEGIN
  1301.     reloTab[reloTabPtr] := offs;
  1302.     INC(reloTabPtr);
  1303.   END PushRelo;
  1304.  
  1305. (*---------------------------------------------------------------------*)
  1306.  
  1307.   PROCEDURE BaseName(VAR path,name: String);
  1308.     VAR i,j : INTEGER;
  1309.   BEGIN
  1310.     i := st.Length(path);
  1311.     WHILE (i > 0) & (path[i-1] # ":") & (path[i-1] # "/") DO
  1312.       DEC(i)
  1313.     END;
  1314.     j := 0;
  1315.     WHILE (i < strLen) & (j < strLen) & (path[i] # 0X) DO
  1316.       name[j] := path[i];
  1317.       INC(i); INC(j)
  1318.     END;
  1319.     IF j < strLen THEN name[j] := 0X END;
  1320.   END BaseName;
  1321.  
  1322. (*---------------------------------------------------------------------*)
  1323.  
  1324.   PROCEDURE SaveMap(keyMap: KeyMapPtr; VAR fileName: String);
  1325.  
  1326.     VAR
  1327.       i,code      : INTEGER;
  1328.       l,offset    : LONGINT;
  1329.       mapName     : String;
  1330.       kmap        : KeyMapPtr;
  1331.       strDeskr    : StrDeskrPtr;
  1332.       deadDeskr   : DeadDeskrPtr;
  1333.       file        : fs.File;
  1334.       ok          : BOOLEAN;
  1335.       node        : e.Node;
  1336.       size        : LONGINT;
  1337.       type        : SHORTSET;
  1338.       nameOffset  : LONGINT;
  1339.       hunkSize    : LONGINT;
  1340.       zero        : SHORTINT;
  1341.  
  1342.  
  1343.     PROCEDURE Write(dat: ARRAY OF BYTE); (* $CopyArrays- *)
  1344.     BEGIN
  1345.       ok := ok & fs.Write(file,dat);
  1346.     END Write;
  1347.  
  1348.     PROCEDURE WriteBlock(from,size: LONGINT);
  1349.     BEGIN
  1350.       IF ok THEN
  1351.         IF size > 0 THEN
  1352.           ok := fs.WriteBlock(file,from,size)
  1353.         END
  1354.       END
  1355.     END WriteBlock;
  1356.  
  1357.     PROCEDURE GetStrDeskrSize(strDeskr:StrDeskrPtr; type:SHORTSET): LONGINT;
  1358.       VAR j: INTEGER; size: LONGINT;
  1359.     BEGIN
  1360.       size := 0;
  1361.       j := 0; WHILE j < NumQual(type) DO
  1362.         INC(size,2);
  1363.         INC(size,strDeskr^[j].len);
  1364.       INC(j) END;
  1365.       RETURN size;
  1366.     END GetStrDeskrSize;
  1367.  
  1368.     PROCEDURE GetDeadDeskrSize(deadDeskr:DeadDeskrPtr;type:SHORTSET):LONGINT;
  1369.       VAR j: INTEGER; size: LONGINT;
  1370.     BEGIN
  1371.       size := 0;
  1372.       j := 0; WHILE j < NumQual(type) DO
  1373.         INC(size,2);
  1374.         IF deadDeskr^[j].type = 1 THEN INC(size,deadLen) END;
  1375.       INC(j) END;
  1376.       RETURN size;
  1377.     END GetDeadDeskrSize;
  1378.  
  1379.   BEGIN
  1380.     IF keyMap = NIL THEN RETURN END;
  1381.     ok := TRUE;
  1382.  
  1383.     BaseName(fileName,mapName);
  1384.     IF mapName[0] = 0X THEN
  1385.       IF rq.Request(kmr,csk,nos,cncl) THEN END;
  1386.       RETURN;
  1387.     END;
  1388.  
  1389.     IF fs.Exists(fileName) THEN
  1390.       IF ~rq.Request(kmr,fae,ovw,cncl) THEN
  1391.         RETURN
  1392.       END;
  1393.     END;
  1394.  
  1395.     IF NOT fs.Open(file,fileName,TRUE) THEN
  1396.       IF rq.Request(kmr,csk,nos,cncl) THEN END;
  1397.       RETURN;
  1398.     END;
  1399.  
  1400.     l := 03F3H;
  1401.     Write(l);
  1402.     l := 0;
  1403.     Write(l);
  1404.     l := 1;
  1405.     Write(l);
  1406.     l := 0;
  1407.     Write(l);
  1408.     Write(l);
  1409.     Write(l);
  1410.     l := 03E9H;
  1411.     Write(l);
  1412.     l := 0;
  1413.     Write(l);
  1414.  
  1415.     node := e.Node(NIL,NIL,0,0,NIL);
  1416.  
  1417.     Write(node);
  1418.     PushRelo(10);
  1419.  
  1420.     l := 76;  Write(l);
  1421.     l := 196; Write(l);
  1422.     l := 46;  Write(l);
  1423.     l := 61;  Write(l);
  1424.     l := 140; Write(l);
  1425.     l := 452; Write(l);
  1426.     l := 54;  Write(l);
  1427.     l := 69;  Write(l);
  1428.  
  1429.     PushRelo(14);
  1430.     PushRelo(18);
  1431.     PushRelo(22);
  1432.     PushRelo(26);
  1433.     PushRelo(30);
  1434.     PushRelo(34);
  1435.     PushRelo(38);
  1436.     PushRelo(42);
  1437.  
  1438.     WriteBlock(keyMap.loCapsable,8);
  1439.     WriteBlock(keyMap.hiCapsable,7);
  1440.     WriteBlock(keyMap.loRepeatable,8);
  1441.     WriteBlock(keyMap.hiRepeatable,7);
  1442.     Write(keyMap.loKeyMapTypes^);
  1443.     Write(keyMap.hiKeyMapTypes^);
  1444.  
  1445.     offset := 676;
  1446.     kmap := s.ADR(keyMap.loKeyMapTypes);
  1447.     i := 0; WHILE i < 120 DO
  1448.       IF i = 64 THEN kmap := s.ADR(keyMap.hiKeyMapTypes) END;
  1449.       code := i MOD 64;
  1450.       type := kmap.loKeyMapTypes[code];
  1451.       IF km.string IN type THEN
  1452.         PushRelo(i*4+196);
  1453.         strDeskr := kmap.loKeyMap[code];
  1454.         Write(offset);
  1455.         size := GetStrDeskrSize(strDeskr,type);
  1456.         INC(offset,size);
  1457.       ELSIF km.dead IN type THEN
  1458.         PushRelo(i*4+196);
  1459.         deadDeskr := kmap.loKeyMap[code];
  1460.         Write(offset);
  1461.         size := GetDeadDeskrSize(deadDeskr,type);
  1462.         INC(offset,size);
  1463.       ELSE
  1464.         Write(kmap.loKeyMap^[code]);
  1465.       END;
  1466.     INC(i) END;
  1467.  
  1468.     kmap := s.ADR(keyMap.loKeyMapTypes);
  1469.     i := 0; WHILE i < 120 DO
  1470.       IF i = 64 THEN kmap := s.ADR(keyMap.hiKeyMapTypes) END;
  1471.       code := i MOD 64;
  1472.       type := kmap.loKeyMapTypes^[code];
  1473.       IF km.string IN type THEN
  1474.         strDeskr := kmap.loKeyMap^[code];
  1475.         size := GetStrDeskrSize(strDeskr,type);
  1476.         WriteBlock(strDeskr,size);
  1477.       ELSIF km.dead IN type THEN
  1478.         deadDeskr := kmap.loKeyMap^[code];
  1479.         size := GetDeadDeskrSize(deadDeskr,type);
  1480.         WriteBlock(deadDeskr,size);
  1481.       END;
  1482.     INC(i) END;
  1483.  
  1484.     nameOffset := offset;
  1485.     size := st.Length(mapName);
  1486.     WriteBlock(s.ADR(mapName),size);
  1487.     zero := 0;
  1488.     Write(zero);
  1489.     INC(offset,size+1);
  1490.     WHILE (offset MOD 4) # 0 DO INC(offset); Write(zero) END;
  1491.     hunkSize := offset DIV 4;
  1492.  
  1493.     l := 03ECH;       Write(l);
  1494.     l := reloTabPtr;  Write(l);
  1495.     l := 0;           Write(l);
  1496.     WHILE reloTabPtr > 0 DO
  1497.       DEC(reloTabPtr);
  1498.       l := reloTab[reloTabPtr];
  1499.       Write(l);
  1500.     END;
  1501.     l := 0;     Write(l);
  1502.     l := 03F2H; Write(l);
  1503.  
  1504.     ok := ok & fs.Move(file,5*4);
  1505.     Write(hunkSize);
  1506.     ok := ok & fs.Move(file,7*4);
  1507.     Write(hunkSize);
  1508.  
  1509.     ok := ok & fs.Move(file,8*4 + 10);
  1510.     Write(nameOffset);
  1511.  
  1512.     ok := fs.Close(file) & ok;
  1513.     IF NOT ok THEN
  1514.       IF rq.Request(kmr,wer,please,forget) THEN
  1515.         IF d.DeleteFile(fileName) THEN END;
  1516.       END;
  1517.     ELSE
  1518.       mapModified := FALSE;
  1519.     END;
  1520.   END SaveMap;
  1521.  
  1522. (*---------------------------------------------------------------------*)
  1523.  
  1524.   PROCEDURE GetDeadLen;
  1525.  
  1526.     VAR
  1527.       code,i,j   : INTEGER;
  1528.       kmap       : KeyMapPtr;
  1529.       deskr      : DeadDeskrPtr;
  1530.       type       : SHORTSET;
  1531.       val        : SHORTINT;
  1532.       offs       : INTEGER;
  1533.       nibble1    : INTEGER;
  1534.       nibble2    : INTEGER;
  1535.       maxNibble2 : INTEGER;
  1536.       maxFaktor  : INTEGER;
  1537.       faktor     : INTEGER;
  1538.  
  1539.   BEGIN
  1540.     maxNibble2 := 0;
  1541.     maxFaktor := 0;
  1542.     i := 0; WHILE i < 120 DO
  1543.       code := i MOD 64;
  1544.       IF i >= 64 THEN
  1545.         kmap := s.ADR(keyMap.hiKeyMapTypes)
  1546.       ELSE
  1547.         kmap := s.ADR(keyMap.loKeyMapTypes)
  1548.       END;
  1549.       type := kmap.loKeyMapTypes^[code];
  1550.       IF km.dead IN type THEN
  1551.         deskr := kmap.loKeyMap^[code];
  1552.         j := 0; WHILE j < NumQual(type) DO
  1553.           IF deskr^[j].type = 8 THEN
  1554.             val := deskr^[j].val;
  1555.             nibble1 := s.LSH(val,-4);
  1556.             nibble2 := val MOD 16;
  1557.             IF nibble1 = 0 THEN
  1558.               IF nibble2 > maxNibble2 THEN maxNibble2 := nibble2 END;
  1559.             ELSE
  1560.               faktor := nibble1 * nibble2;
  1561.               IF faktor > maxFaktor THEN maxFaktor := faktor END;
  1562.             END;
  1563.           END;
  1564.         INC(j) END;
  1565.       END;
  1566.     INC(i) END;
  1567.     deadLen := maxFaktor + maxNibble2 + 1;
  1568.     IF deadLen <  1 THEN deadLen :=  1 END;
  1569.     IF deadLen > 32 THEN deadLen := 32 END;
  1570.     (* $IF debug *)
  1571.     IF ARP.FPrintf(io.out,"DeadLen = %ld.\n",deadLen) = 0 THEN END;
  1572.     (* $END *)
  1573.   END GetDeadLen;
  1574.  
  1575. (*---------------------------------------------------------------------*)
  1576.  
  1577.   PROCEDURE SetUp(firstTime: BOOLEAN);
  1578.     VAR i: INTEGER; type: SHORTSET;
  1579.   BEGIN
  1580.     makeGads := firstTime;
  1581.     gadCnt := 0;
  1582.     strCnt := 0;
  1583.  
  1584.     win := I.OpenWindow(nw);
  1585.  
  1586.     rq.Assert(win # NIL,cow);
  1587.  
  1588.     rp := win.rPort;
  1589.     g.SetFont(rp,font);
  1590.     g.SetAPen(rp,2);
  1591.     g.RectFill(rp,20,Y1,610,105+Y1);
  1592.     I.DrawImage(rp,kmePic,400,20);
  1593.     g.SetAfPt(rp,s.ADR(pat),1);
  1594.  
  1595.     DrawKeyRow(keyRow0,20);
  1596.     DrawKeyRow(keyRow1,25+keyHeight);
  1597.     DrawKeyRow(keyRow2,25+keyHeight*2);
  1598.     DrawKeyRow(keyRow3,25+keyHeight*3);
  1599.     DrawKeyRow(keyRow4,25+keyHeight*4);
  1600.     DrawKeyRow(keyRow5,25+keyHeight*5);
  1601.  
  1602.     MakeGadget(30+X1 ,110+Y1,"LOAD",idLoad);
  1603.     MakeGadget(116+X1,110+Y1,"SAVE",idSave);
  1604.     MakeGadget(202+X1,110+Y1,"ABOUT",idAbout);
  1605.     MakeGadget(30+X1 ,126+Y1,"SHIFT",idShift);
  1606.     MakeGadget(116+X1,126+Y1,"ALT",idAlt);
  1607.     MakeGadget(186+X1,126+Y1,"CONTROL",idControl);
  1608.     MakeGadget(30+X1 ,142+Y1,"DOWNUP",idDownup);
  1609.     MakeGadget(98+X1 ,142+Y1,"DEAD",idDead);
  1610.     MakeGadget(150+X1,142+Y1,"STRING",idString);
  1611.     MakeGadget(218+X1,142+Y1,"NOP",idNop);
  1612.     MakeGadget(30+X1 ,158+Y1,"CAPSABLE",idCapsable);
  1613.     MakeGadget(162+X1,158+Y1,"REPEATABLE",idRepeatable);
  1614.     MakeGadget(30+X1 ,174+Y1,"QUIT",idQuit);
  1615.     MakeGadget(108+X1,174+Y1,"ICONIFY",idIconify);
  1616.     MakeGadget(210+X1,174+Y1,"UNDO",idUndo);
  1617.  
  1618.     i := 0; WHILE i < 8 DO
  1619.       MakeStrGadget(380+X2,107+Y1+i*10,192,idStr+i);
  1620.     INC(i) END;
  1621.  
  1622.     i := 0; WHILE i < 8 DO
  1623.       MakeGadget(580,107+Y1+i*10,nos,idMod+i);
  1624.     INC(i) END;
  1625.  
  1626.     I.RefreshGList(s.ADR(gad[0]),win,NIL,gadCnt);
  1627.  
  1628.     IF firstTime THEN
  1629.       type := SHORTSET{}
  1630.     ELSE
  1631.       GetType(type);
  1632.     END;
  1633.  
  1634.     SetStrGads(type);
  1635.     SetModGads;
  1636.  
  1637.   END SetUp;
  1638.  
  1639. (*---------------------------------------------------------------------*)
  1640.  
  1641.   PROCEDURE Quit;
  1642.   BEGIN
  1643.     IF keyModified THEN
  1644.       SetKey(rawCode);
  1645.       keyModified := FALSE;
  1646.     END;
  1647.     IF ~mapModified OR rq.Request(kmr,quit,please,forget) THEN
  1648.       HALT(0)
  1649.     END;
  1650.   END Quit;
  1651.  
  1652. (*---------------------------------------------------------------------*)
  1653.  
  1654.  
  1655. BEGIN
  1656.  
  1657.   win := NIL; font := NIL; seg := NIL;
  1658.   lastKeyGad := NIL; keyModified := FALSE;
  1659.   rawCode := -1; reloTabPtr := 0; mapModified := FALSE;
  1660.   iconX := 50; iconY := 50;
  1661.   fileName := "DEVS:keymaps/";
  1662.  
  1663.   INCL(ol.MemReqs,e.chip);
  1664.   NEW(chipBuf);
  1665.   NEW(zz);
  1666.   NEW(kmeIconData);
  1667.   NEW(kmePicData);
  1668.   EXCL(ol.MemReqs,e.chip);
  1669.  
  1670.   rq.Assert((chipBuf # NIL) & (zz # NIL) &
  1671.             (kmeIconData # NIL) & (kmePicData # NIL),ooc);
  1672.  
  1673.   e.CopyMem(ZZData,zz^,s.SIZE(zz^));
  1674.   e.CopyMem(KmeIconData,kmeIconData^,s.SIZE(kmeIconData^));
  1675.   e.CopyMem(KmePicData,kmePicData^,s.SIZE(kmePicData^));
  1676.  
  1677.   kmeIcon := I.Image(0,0,kmeIconWidth,kmeIconHeight,2,NIL,SHORTSET{0,1},SHORTSET{},NIL);
  1678.   kmeIcon.imageData := kmeIconData;
  1679.  
  1680.   kmePic := I.Image(0,0,kmePicWidth,kmePicHeight,1,NIL,SHORTSET{1},SHORTSET{},NIL);
  1681.   kmePic.imageData := kmePicData;
  1682.  
  1683.   i := 32; WHILE i <= 39 DO
  1684.     hiTypes[i] := SHORTSET{km.nop};
  1685.   INC(i) END;
  1686.  
  1687.   dfltKeyMap.loKeyMapTypes := s.ADR(loTypes);
  1688.   dfltKeyMap.hiKeyMapTypes := s.ADR(hiTypes);
  1689.   dfltKeyMap.loKeyMap := s.ADR(loMap);
  1690.   dfltKeyMap.hiKeyMap := s.ADR(hiMap);
  1691.   dfltKeyMap.loCapsable := s.ADR(loCaps);
  1692.   dfltKeyMap.hiCapsable := s.ADR(hiCaps);
  1693.   dfltKeyMap.loRepeatable := s.ADR(loRepeat);
  1694.   dfltKeyMap.hiRepeatable := s.ADR(hiRepeat);
  1695.   deadLen := 18;
  1696.  
  1697.   keyMap := s.ADR(dfltKeyMap);
  1698.  
  1699.   attr := g.TextAttr(s.ADR("topaz.font"),8,g.normalFont,SHORTSET{g.romFont});
  1700.   font := g.OpenFont(attr);
  1701.   IF font = NIL THEN HALT(0) END;
  1702.   pat[0] := 05555U;
  1703.   pat[1] := 0AAAAU;
  1704.  
  1705.   nw := I.NewWindow(0,0,640,200,-1,-1,
  1706.                     LONGSET{I.closeWindow,I.gadgetUp,I.rawKey},
  1707.                     LONGSET{I.windowDepth,I.windowDrag,I.windowClose,I.activate},
  1708.                     NIL,NIL, s.ADR("KME"),NIL,NIL,90,40,-1,-1,{I.wbenchScreen});
  1709.  
  1710.  
  1711.   SetUp(TRUE);
  1712.  
  1713.   LOOP
  1714.     e.WaitPort(win.userPort);
  1715.     REPEAT
  1716.       msg := e.GetMsg(win.userPort);
  1717.     UNTIL msg # NIL;
  1718.     mes := msg^;
  1719.     e.ReplyMsg(msg);
  1720.  
  1721.     IF I.closeWindow IN mes.class THEN
  1722.       Quit;
  1723.  
  1724.     ELSIF I.rawKey IN mes.class THEN
  1725.       IF mes.code < 128 THEN
  1726.         gadget := FindGadget(idKey);
  1727.         WHILE (gadget # NIL)               &
  1728.               (gadget.gadgetID = idKey)    &
  1729.               (gadget.userData # mes.code)   DO
  1730.           gadget := gadget.nextGadget;
  1731.         END;
  1732.         IF gadget.userData = mes.code THEN
  1733.           IF lastKeyGad # NIL THEN
  1734.             INCL(lastKeyGad.flags,I.selected);
  1735.             I.RefreshGList(lastKeyGad,win,NIL,1);
  1736.             EXCL(lastKeyGad.flags,I.selected);
  1737.           END;
  1738.           INCL(gadget.flags,I.selected);
  1739.           I.RefreshGList(gadget,win,NIL,1);
  1740.           oldCode := rawCode;
  1741.           lastKeyGad := gadget;
  1742.           rawCode := SHORT(gadget.userData);
  1743.           IF keyModified THEN
  1744.             SetKey(oldCode);
  1745.           END;
  1746.           GetKey(rawCode);
  1747.           keyModified := FALSE;
  1748.         END;
  1749.       END;
  1750.  
  1751.     ELSIF I.gadgetUp IN mes.class THEN
  1752.       clickedGad := mes.iAddress;
  1753.       gadID := clickedGad.gadgetID;
  1754.  
  1755.       CASE gadID OF
  1756.  
  1757.       | idQuit:
  1758.         Quit;
  1759.  
  1760.       | idKey :
  1761.         IF lastKeyGad # NIL THEN
  1762.           INCL(lastKeyGad.flags,I.selected);
  1763.           I.RefreshGList(lastKeyGad,win,NIL,1);
  1764.           EXCL(lastKeyGad.flags,I.selected);
  1765.           INCL(clickedGad.flags,I.selected);
  1766.         END;
  1767.  
  1768.         oldCode := rawCode;
  1769.         lastKeyGad := clickedGad;
  1770.         rawCode := SHORT(clickedGad.userData);
  1771.         IF keyModified THEN
  1772.           SetKey(oldCode);
  1773.         END;
  1774.         GetKey(rawCode);
  1775.         keyModified := FALSE;
  1776.  
  1777.       | idLoad:
  1778.         IF keyModified THEN
  1779.           SetKey(rawCode);
  1780.           keyModified := FALSE;
  1781.         END;
  1782.         IF ~mapModified OR rq.Request(kmr,load,please,forget) THEN
  1783.           IF fr.FileReq("Load keymap:",fileName) THEN
  1784.             Busy(win);
  1785.             newSeg := d.LoadSeg(fileName);
  1786.             I.ClearPointer(win);
  1787.             IF newSeg # NIL THEN
  1788.               IF seg # NIL THEN d.UnLoadSeg(seg) END;
  1789.               seg := newSeg;
  1790.               dummy := seg;
  1791.               keyMap := dummy + 4 + s.SIZE(e.Node);
  1792.               GetDeadLen;
  1793.               ClearGadgets;
  1794.               mapModified := FALSE;
  1795.             ELSE
  1796.               IF rq.Request(kmr,clk,nos,cncl) THEN END;
  1797.             END;
  1798.           END;
  1799.         END;
  1800.  
  1801.       | idSave:
  1802.         IF keyModified THEN
  1803.           SetKey(rawCode);
  1804.           keyModified := FALSE;
  1805.         END;
  1806.         IF fr.FileReq("Save keymap:",fileName) THEN
  1807.           Busy(win);
  1808.           SaveMap(keyMap,fileName);
  1809.           I.ClearPointer(win);
  1810.         END;
  1811.  
  1812.       | idUndo:
  1813.         IF keyModified THEN
  1814.           GetKey(rawCode);
  1815.           keyModified := FALSE;
  1816.         END;
  1817.  
  1818.       | idDead,idString:
  1819.         keyModified := TRUE;
  1820.         LOOP
  1821.           IF I.selected IN clickedGad.flags THEN
  1822.             gadget := FindGadget(idNop);
  1823.             IF I.selected IN gadget.flags THEN
  1824.               I.RefreshGList(clickedGad,win,NIL,1);
  1825.               EXCL(clickedGad.flags,I.selected);
  1826.               EXIT;
  1827.             ELSE
  1828.               IF gadID = idDead THEN
  1829.                 gadget := FindGadget(idString);
  1830.               ELSE
  1831.                 gadget := FindGadget(idDead);
  1832.               END;
  1833.               IF I.selected IN gadget.flags THEN
  1834.                 I.RefreshGList(gadget,win,NIL,1);
  1835.                 EXCL(gadget.flags,I.selected);
  1836.               END;
  1837.             END;
  1838.           END;
  1839.           GetType(type);
  1840.           SetStrGads(type);
  1841.           EXIT;
  1842.         END;
  1843.  
  1844.       | idAlt,idControl,idShift:
  1845.         keyModified := TRUE;
  1846.         LOOP
  1847.           IF I.selected IN clickedGad.flags THEN
  1848.             gadget := FindGadget(idNop);
  1849.             IF I.selected IN gadget.flags THEN
  1850.               I.RefreshGList(clickedGad,win,NIL,1);
  1851.               EXCL(clickedGad.flags,I.selected);
  1852.               EXIT;
  1853.             END;
  1854.           END;
  1855.           GetType(type);
  1856.           SetStrGads(type);
  1857.           EXIT
  1858.         END;
  1859.  
  1860.       | idCapsable,idRepeatable,idDownup:
  1861.         keyModified := TRUE;
  1862.         IF I.selected IN clickedGad.flags THEN
  1863.           gadget := FindGadget(idNop);
  1864.           IF I.selected IN gadget.flags THEN
  1865.             I.RefreshGList(clickedGad,win,NIL,1);
  1866.             EXCL(clickedGad.flags,I.selected);
  1867.           END;
  1868.         END;
  1869.  
  1870.       | idNop:
  1871.         keyModified := TRUE;
  1872.         IF I.selected IN clickedGad.flags THEN
  1873.           I.RefreshGList(FindGadget(idShift),win,NIL,6);
  1874.           I.RefreshGList(FindGadget(idCapsable),win,NIL,2);
  1875.           gadget := FindGadget(idShift);   EXCL(gadget.flags,I.selected);
  1876.           gadget := FindGadget(idAlt);     EXCL(gadget.flags,I.selected);
  1877.           gadget := FindGadget(idControl); EXCL(gadget.flags,I.selected);
  1878.           gadget := FindGadget(idDownup);  EXCL(gadget.flags,I.selected);
  1879.           gadget := FindGadget(idString);  EXCL(gadget.flags,I.selected);
  1880.           gadget := FindGadget(idDead);    EXCL(gadget.flags,I.selected);
  1881.           gadget := FindGadget(idCapsable);   EXCL(gadget.flags,I.selected);
  1882.           gadget := FindGadget(idRepeatable); EXCL(gadget.flags,I.selected);
  1883.         END;
  1884.         GetType(type);
  1885.         SetStrGads(type);
  1886.  
  1887.       | idMod .. idMod + 7:
  1888.         keyModified := TRUE;
  1889.         clickedGad.userData := (SHORT(clickedGad.userData) + 1) MOD 3;
  1890.         SetModGads;
  1891.  
  1892.       | idAbout:
  1893.         IF rq.Request(kme,cprt,nos,ok) THEN END;
  1894.  
  1895.       | idStr..idStr+7:
  1896.         i := gadID - idStr;
  1897.         AsciiToRaw(buffer[i],string);
  1898.         gadget := FindGadget(idMod+i);
  1899.         RawToAscii(string,buffer[i],gadget.userData = 2);
  1900.         I.RefreshGList(FindGadget(idStr+i),win,NIL,1);
  1901.         keyModified := TRUE;
  1902.  
  1903.       | idIconify:
  1904.         nw.leftEdge := win.leftEdge;
  1905.         nw.topEdge  := win.topEdge;
  1906.         I.CloseWindow(win); win := NIL;
  1907.         ic.Iconify(iconX,iconY,s.ADR(kmeIcon));
  1908.         SetUp(FALSE);
  1909.  
  1910.       ELSE
  1911.       END (*CASE*)
  1912.     END (*IF*)
  1913.   END (*LOOP*)
  1914.  
  1915. CLOSE
  1916.  
  1917.   IF seg  # NIL THEN d.UnLoadSeg(seg) END;
  1918.   IF win  # NIL THEN I.CloseWindow(win) END;
  1919.   IF font # NIL THEN g.CloseFont(font) END;
  1920.  
  1921. END KME.
  1922.  
  1923.